﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.IO;
using L32Assembler.Registers;
namespace L32Assembler
{
    class Program
    {
        static Registers.Registers registers = new Registers.Registers();
        static ArrayList Procedures = new ArrayList();
        static ArrayList ProcedureContents = new ArrayList();
        static bool isInProcedure = false;
        static string curProcName = "";
        static void Main(string[] args)
        {
            registers.InitializeComponent();
            string file = Console.ReadLine();
            StreamReader sr = new StreamReader(file);
            string full = sr.ReadToEnd();
            sr.Close();
            string[] lines = full.Split(new string[] {"\r\n"}, StringSplitOptions.None);
            foreach (string line in lines)
            {
                ExecuteLine(line);
            }
            //PrintReg();
            Console.Read();
        }
        static void ExecuteLine(string line)
        {
            string[] cmd = line.Split(' ');
            if (isInProcedure && cmd[0]!="END")
            {
                int i = Procedures.IndexOf(curProcName);
                if (i != -1)
                {
                    (ProcedureContents[i] as ArrayList).Add(line);
                }

            }
            else
            {

                if (cmd[0].EndsWith(":") && cmd.Length == 1 && cmd[0]!="END")
                {
                    NewProcedure(cmd);
                }
                else
                {
                    switch (cmd[0])
                    {
                        case "END":
                            isInProcedure = false;
                            break;
                        case "MOVE":
                            Move(cmd);
                            break;
                        case "ADD":
                            ADD(cmd);
                            break;
                        case "SUB":
                            SUB(cmd);
                            break;
                        case "INC":
                            INC(cmd);
                            break;
                        case "DEC":
                            DEC(cmd);
                            break;
                        case "INT":
                            INT(cmd);
                            break;
                        case "PUSHA":
                            PUSHA();
                            break;
                        case "POPA":
                            POPA();
                            break;
                        case "JMP":
                            JMP(cmd);
                            break;
                    }
                }
            }
        }
        static void Move(string[] cmd)
        {
            cmd[1] = cmd[1].Remove(cmd[1].Length - 1, 1);
            if (cmd[1] == "A")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.A = GetRegisterValue(cmd[2]);
                else
                    registers.A = GetNextVal(cmd);
                
            }
            else if (cmd[1] == "B")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.B = GetRegisterValue(cmd[2]);
                else registers.B = GetNextVal(cmd);
            }
            else if (cmd[1] == "C")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.C = GetRegisterValue(cmd[2]);
                else registers.C = GetNextVal(cmd);
            }
            else if (cmd[1] == "D")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.D = GetRegisterValue(cmd[2]);
                else registers.D = GetNextVal(cmd);
            }
            else if (cmd[1] == "S")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.S = GetRegisterValue(cmd[2]);
                else
                    registers.S = GetNextVal(cmd);
            }
            else if (cmd[1] == "AH")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.AH = GetRegisterValue(cmd[2]);
                else
                    registers.AH = GetNextVal(cmd);
            }
            else if (cmd[1] == "BL")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.BL = GetRegisterValue(cmd[2]);
                else
                    registers.BL = GetNextVal(cmd);
            }
        }
        static object GetRegisterValue(string name)
        {
            if (name == "A")
                return registers.A;
            else if (name == "B")
                return registers.B;
            else if (name == "C")
                return registers.C;
            else if (name == "D")
                return registers.D;
            else if (name == "S")
                return registers.S;
            else if (name == "AH")
                return registers.AH;
            else if (name == "BL")
                return registers.BL;
            else
                return new object();
        }
        static string GetNextVal(string[] cmd)
        {
            string retstr = "";
            for (int i = 2; i < cmd.Length; i++)
            { 
                if(retstr=="")
                    retstr += cmd[i];
                else
                    retstr += " " + cmd[i];
            }
            return retstr;
        }
        static void PrintReg()
        {
            Console.WriteLine(registers.S.ToString());
        }
        static bool isNumerical(string arg)
        {
            if (arg.Contains("1") || arg.Contains("2") || arg.Contains("3") || arg.Contains("4")
                || arg.Contains("5") || arg.Contains("6") || arg.Contains("7") || arg.Contains("8") || arg.Contains("9") || arg.Contains("0"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        static void ADD(string[] cmd)
        {
            cmd[1] = cmd[1].Remove(cmd[1].Length - 1, 1);
            if (cmd[1] == "A")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.A = System.Convert.ToInt32(GetRegisterValue("A")) + System.Convert.ToInt32(GetRegisterValue(cmd[2]));
                else registers.A = System.Convert.ToInt32(GetRegisterValue("A")) + System.Convert.ToInt32(GetNextVal(cmd));
            }
            else if (cmd[1] == "B")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.B = System.Convert.ToInt32(GetRegisterValue("B")) + System.Convert.ToInt32(GetRegisterValue(cmd[2]));
                else registers.B = System.Convert.ToInt32(GetRegisterValue("B")) + System.Convert.ToInt32(GetNextVal(cmd));
            }
            else if (cmd[1] == "C")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.C = System.Convert.ToInt32(GetRegisterValue("C")) + System.Convert.ToInt32(GetRegisterValue(cmd[2]));
                else registers.C = System.Convert.ToInt32(GetRegisterValue("C")) + System.Convert.ToInt32(GetNextVal(cmd));
            }
            else if (cmd[1] == "D")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.D = System.Convert.ToInt32(GetRegisterValue("D")) + System.Convert.ToInt32(GetRegisterValue(cmd[2]));
                else registers.D = System.Convert.ToInt32(GetRegisterValue("D")) + System.Convert.ToInt32(GetNextVal(cmd));
            }
        }
        static void SUB(string[] cmd)
        {
            cmd[1] = cmd[1].Remove(cmd[1].Length - 1, 1);
            if (cmd[1] == "A")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.A = System.Convert.ToInt32(GetRegisterValue("A")) - System.Convert.ToInt32(GetRegisterValue(cmd[2]));
                else registers.A = System.Convert.ToInt32(GetRegisterValue("A")) - System.Convert.ToInt32(GetNextVal(cmd));
            }
            else if (cmd[1] == "B")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.B = System.Convert.ToInt32(GetRegisterValue("B")) - System.Convert.ToInt32(GetRegisterValue(cmd[2]));
                else registers.B = System.Convert.ToInt32(GetRegisterValue("B")) - System.Convert.ToInt32(GetNextVal(cmd));
            }
            else if (cmd[1] == "C")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.C = System.Convert.ToInt32(GetRegisterValue("C")) - System.Convert.ToInt32(GetRegisterValue(cmd[2]));
                else registers.C = System.Convert.ToInt32(GetRegisterValue("C")) - System.Convert.ToInt32(GetNextVal(cmd));
            }
            else if (cmd[1] == "D")
            {
                if (!cmd[2].Contains("\"") && !isNumerical(GetNextVal(cmd)))
                    registers.D = System.Convert.ToInt32(GetRegisterValue("D")) - System.Convert.ToInt32(GetRegisterValue(cmd[2]));
                else registers.D = System.Convert.ToInt32(GetRegisterValue("D")) - System.Convert.ToInt32(GetNextVal(cmd));
            }
        }
        static void INC(string[] cmd)
        {
            if (cmd[1] == "A")
            {
                registers.A = System.Convert.ToInt32(GetRegisterValue("A")) + 1;
            }
            else if (cmd[1] == "B")
            {
                registers.B = System.Convert.ToInt32(GetRegisterValue("B")) + 1;
            }
            else if (cmd[1] == "C")
            {
                registers.C = System.Convert.ToInt32(GetRegisterValue("C")) + 1;
            }
            else if (cmd[1] == "D")
            {
                registers.D = System.Convert.ToInt32(GetRegisterValue("A")) + 1;
            }
        }
        static void DEC(string[] cmd)
        {
            if (cmd[1] == "A")
            {
                registers.A = System.Convert.ToInt32(GetRegisterValue("A")) - 1;
            }
            else if (cmd[1] == "B")
            {
                registers.B = System.Convert.ToInt32(GetRegisterValue("B")) - 1;
            }
            else if (cmd[1] == "C")
            {
                registers.C = System.Convert.ToInt32(GetRegisterValue("C")) - 1;
            }
            else if (cmd[1] == "D")
            {
                registers.D = System.Convert.ToInt32(GetRegisterValue("A")) - 1;
            }
        }
        static void INT(string[] cmd)
        {
            if (cmd[1] == "10H")
            {
                switch (registers.AH.ToString())
                { 
                    case "09h":
                        Console.WriteLine(registers.S.ToString());
                        break;
                    case "0Bh":
                        break;
                }
            }
        }
        static void ChangeColor(string val)
        { 
            
        }
        static void PUSHA()
        {
            registers.PUSHA();
        }
        static void POPA()
        {
            registers.POPA();
        }
        static void NewProcedure(string[] cmd)
        {
            cmd[0] = cmd[0].Remove(cmd[0].Length - 1, 1);
            Procedures.Add(cmd[0]);
            isInProcedure = true;
            ProcedureContents.Add(new ArrayList());
            curProcName = cmd[0];
        }
        static void JMP(string[] cmd)
        {
            int i = Procedures.IndexOf(cmd[1]);
            if (i != -1)
            {
                foreach (object val in (ProcedureContents[i] as ArrayList))
                {
                    ExecuteLine(val.ToString());
                }
            }
        }
    }
}
